package com.gitee.feizns.quickstart.web.ex.impl;

import com.gitee.feizns.quickstart.domain.vo.Ret;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;

/**
 * Spring Mvc 处理请求参数格式错误 @RequestParam 上 validate
 * 失败后抛出的异常是javax.validation.ConstraintViolationException
 * 需要在类上或是方法上添加 @Validated 并保证该控制器方法不是static的
 * @link <a href="https://juejin.cn/post/6844904003684302861">Spring 参数校验的异常处理</a>
 * @see javax.validation.ConstraintViolationException
 * @author feizns
 * @since 2019/7/19
 */
@NoArgsConstructor
public class ConstraintViolationExceptionHandler extends AbstractExceptionHandler<ConstraintViolationException> {

    /**
     * 响应的Http状态
     */
    private HttpStatus httpStatus = HttpStatus.BAD_REQUEST;

    public ConstraintViolationExceptionHandler(HttpStatus httpStatus) {
        this.httpStatus = httpStatus;
    }

    /**
     * 对于 ConstraintViolationException 响应 400
     * 并判断是否有默认消息
     * @param e {@link ConstraintViolationExceptionHandler}
     * @return {@link ResponseEntity}
     */
    @Override
    public ResponseEntity<Ret<?>> handle(ConstraintViolationException e) {
        return ResponseEntity.status(httpStatus).body(Ret.error(HttpStatus.BAD_REQUEST.value(), getMessage(e)));
    }

    /**
     * 对于拥有模板的字段，则补充字段名称
     * @param e {@link ConstraintViolationException}
     * @return 错误消息
     */
    private String getMessage(ConstraintViolationException e) {
        Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
        StringBuilder message = new StringBuilder();
        for (ConstraintViolation<?> violation : violations) {
            message.append(String.format("参数:[%s]%s. ", violation.getPropertyPath(), violation.getMessage()));
        }
        return message.toString();
    }

}
